const std = @import("std");
const virtual_actor = @import("../src/actor/virtual_actor.zig");
const actor_system = @import("../src/actor/actor_system.zig");

/// 用户 Actor 状态
const UserState = struct {
    username: []const u8 = "",
    email: []const u8 = "",
    balance: f64 = 0.0,
    created_at: i64 = 0,
};

/// 用户 Actor - Orleans 风格的 Virtual Actor
const UserActor = struct {
    base: virtual_actor.VirtualActor(UserState),
    
    const Self = @This();
    
    /// 设置用户信息
    pub fn setInfo(self: *Self, username: []const u8, email: []const u8) !void {
        self.base.state.username = username;
        self.base.state.email = email;
        self.base.touch();
    }
    
    /// 充值
    pub fn deposit(self: *Self, amount: f64) !void {
        if (amount <= 0) return error.InvalidAmount;
        
        self.base.state.balance += amount;
        self.base.touch();
        
        std.debug.print("用户 {s} 充值 {d}，余额: {d}\n", .{
            self.base.id,
            amount,
            self.base.state.balance,
        });
    }
    
    /// 扣费
    pub fn withdraw(self: *Self, amount: f64) !void {
        if (amount <= 0) return error.InvalidAmount;
        if (self.base.state.balance < amount) return error.InsufficientBalance;
        
        self.base.state.balance -= amount;
        self.base.touch();
        
        std.debug.print("用户 {s} 扣费 {d}，余额: {d}\n", .{
            self.base.id,
            amount,
            self.base.state.balance,
        });
    }
    
    /// 转账（跨 Actor 调用）
    pub fn transfer(self: *Self, target: *UserActor, amount: f64) !void {
        if (amount <= 0) return error.InvalidAmount;
        if (self.base.state.balance < amount) return error.InsufficientBalance;
        
        // 扣除自己的余额
        self.base.state.balance -= amount;
        
        // 给目标充值
        try target.deposit(amount);
        
        self.base.touch();
        
        std.debug.print("用户 {s} 向 {s} 转账 {d}\n", .{
            self.base.id,
            target.base.id,
            amount,
        });
    }
    
    /// 获取余额
    pub fn getBalance(self: *Self) f64 {
        self.base.touch();
        return self.base.state.balance;
    }
};

/// 聊天室 Actor 状态
const ChatRoomState = struct {
    name: []const u8 = "",
    message_count: usize = 0,
};

/// 聊天室 Actor
const ChatRoomActor = struct {
    base: virtual_actor.VirtualActor(ChatRoomState),
    members: std.ArrayList([]const u8),
    
    const Self = @This();
    
    pub fn init(allocator: std.mem.Allocator, base: virtual_actor.VirtualActor(ChatRoomState)) Self {
        return .{
            .base = base,
            .members = std.ArrayList([]const u8).init(allocator),
        };
    }
    
    pub fn deinit(self: *Self) void {
        self.members.deinit();
    }
    
    /// 加入聊天室
    pub fn join(self: *Self, user_id: []const u8) !void {
        // 检查是否已经是成员
        for (self.members.items) |member| {
            if (std.mem.eql(u8, member, user_id)) {
                return; // 已经是成员
            }
        }
        
        try self.members.append(user_id);
        self.base.touch();
        
        std.debug.print("用户 {s} 加入聊天室 {s}\n", .{user_id, self.base.id});
    }
    
    /// 发送消息
    pub fn sendMessage(self: *Self, sender: []const u8, content: []const u8) !void {
        self.base.state.message_count += 1;
        self.base.touch();
        
        std.debug.print("[{s}] {s}: {s}\n", .{
            self.base.state.name,
            sender,
            content,
        });
    }
};

/// 消息类型
const UserMessage = union(enum) {
    deposit: f64,
    withdraw: f64,
    get_balance: *f64,
};

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    std.debug.print("=== Orleans 风格 Actor 系统演示 ===\n\n", .{});
    
    // 1. 初始化 Actor 系统
    std.debug.print("1. 初始化 Actor 系统\n", .{});
    var system = try actor_system.ActorSystem.init(allocator, .{
        .cluster_mode = false,
        .idle_timeout = 300,
        .persistence = .{ .type = .memory },
    });
    defer system.deinit();
    
    // 2. 创建存储
    var storage = virtual_actor.MemoryStorage(UserState).init(allocator);
    defer storage.deinit();
    
    // 3. 获取 Actor（自动激活）
    std.debug.print("\n2. 获取 Virtual Actor（自动激活）\n", .{});
    
    const user1_id = virtual_actor.ActorId{
        .type_name = "UserActor",
        .id = "user_001",
    };
    const user1_base = try system.registry.getOrCreate(
        virtual_actor.VirtualActor(UserState),
        user1_id,
        &storage,
    );
    var user1 = UserActor{ .base = user1_base.* };
    
    const user2_id = virtual_actor.ActorId{
        .type_name = "UserActor",
        .id = "user_002",
    };
    const user2_base = try system.registry.getOrCreate(
        virtual_actor.VirtualActor(UserState),
        user2_id,
        &storage,
    );
    var user2 = UserActor{ .base = user2_base.* };
    
    std.debug.print("用户1 状态: {}\n", .{user1.base.lifecycle});
    std.debug.print("用户2 状态: {}\n", .{user2.base.lifecycle});
    
    // 4. 设置用户信息
    std.debug.print("\n3. 设置用户信息\n", .{});
    try user1.setInfo("张三", "zhangsan@example.com");
    try user2.setInfo("李四", "lisi@example.com");
    
    // 5. 充值
    std.debug.print("\n4. 充值操作\n", .{});
    try user1.deposit(100.0);
    try user2.deposit(50.0);
    
    // 6. 转账（跨 Actor 调用）
    std.debug.print("\n5. 转账操作（跨 Actor 调用）\n", .{});
    try user1.transfer(&user2, 30.0);
    
    // 7. 查询余额
    std.debug.print("\n6. 查询余额\n", .{});
    const balance1 = user1.getBalance();
    const balance2 = user2.getBalance();
    std.debug.print("用户1余额: {d}\n", .{balance1});
    std.debug.print("用户2余额: {d}\n", .{balance2});
    
    // 8. 失活并保存状态
    std.debug.print("\n7. 失活并保存状态\n", .{});
    try user1.base.deactivate(&storage);
    try user2.base.deactivate(&storage);
    std.debug.print("用户1 状态: {}\n", .{user1.base.lifecycle});
    std.debug.print("用户2 状态: {}\n", .{user2.base.lifecycle});
    
    // 9. 重新激活（从存储加载）
    std.debug.print("\n8. 重新激活（从存储加载）\n", .{});
    try user1.base.activate(&storage);
    try user2.base.activate(&storage);
    std.debug.print("用户1 余额（已恢复）: {d}\n", .{user1.base.state.balance});
    std.debug.print("用户2 余额（已恢复）: {d}\n", .{user2.base.state.balance});
    
    // 10. Turn-based 并发演示
    std.debug.print("\n9. Turn-based 并发演示\n", .{});
    var executor = actor_system.TurnBasedExecutor(UserActor, UserMessage).init(allocator, &user1);
    defer executor.deinit();
    
    try executor.start(handleUserMessage);
    
    // 发送消息
    try executor.send(.{ .deposit = 20.0 });
    try executor.send(.{ .withdraw = 10.0 });
    
    var result: f64 = 0;
    try executor.send(.{ .get_balance = &result });
    
    // 等待消息处理
    std.time.sleep(100 * std.time.ns_per_ms);
    
    executor.stop();
    
    std.debug.print("\n=== 演示完成 ===\n", .{});
    std.debug.print("\nOrleans 核心特性已实现：\n", .{});
    std.debug.print("✓ Virtual Actor - 按需激活\n", .{});
    std.debug.print("✓ 自动生命周期管理 - 激活/失活\n", .{});
    std.debug.print("✓ 状态持久化 - 自动保存和恢复\n", .{});
    std.debug.print("✓ 单线程执行 - Turn-based 并发\n", .{});
    std.debug.print("✓ 位置透明 - 统一的调用接口\n", .{});
}

fn handleUserMessage(actor: *UserActor, msg: UserMessage) !void {
    switch (msg) {
        .deposit => |amount| {
            try actor.deposit(amount);
        },
        .withdraw => |amount| {
            try actor.withdraw(amount);
        },
        .get_balance => |result_ptr| {
            result_ptr.* = actor.getBalance();
        },
    }
}

test "Virtual Actor 生命周期" {
    const testing = std.testing;
    
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    
    var storage = virtual_actor.MemoryStorage(UserState).init(allocator);
    defer storage.deinit();
    
    var system = try actor_system.ActorSystem.init(allocator, .{});
    defer system.deinit();
    
    const actor_id = virtual_actor.ActorId{
        .type_name = "UserActor",
        .id = "test_user",
    };
    
    const actor_base = try system.registry.getOrCreate(
        virtual_actor.VirtualActor(UserState),
        actor_id,
        &storage,
    );
    var actor = UserActor{ .base = actor_base.* };
    
    // 测试充值
    try actor.deposit(100.0);
    try testing.expect(actor.getBalance() == 100.0);
    
    // 测试扣费
    try actor.withdraw(30.0);
    try testing.expect(actor.getBalance() == 70.0);
    
    // 测试失活和重新激活
    try actor.base.deactivate(&storage);
    try actor.base.activate(&storage);
    try testing.expect(actor.base.state.balance == 70.0);
}
